package com.qibao.toolkit.exception.strategy.impl;

import com.qibao.toolkit.exception.strategy.AbstractExceptionHandleStrategy;
import com.qibao.toolkit.exception.strategy.BaseExceptionHandleStrategyAware;
import com.qibao.toolkit.exception.strategy.ExceptionHandleType;
import com.qibao.toolkit.web.ResponseModel;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;

import java.util.List;
import java.util.Map;

/**
 * @author wangcheng
 * @version $Id: BindExceptionHandleStrategy.java, v0.1 2018/9/28 9:39 wangcheng Exp $$
 */
@ExceptionHandleType({BindException.class, MethodArgumentNotValidException.class})
public class BindExceptionHandleStrategy extends AbstractExceptionHandleStrategy implements
        BaseExceptionHandleStrategyAware {

    private static final Logger logger = LoggerFactory.getLogger(BindExceptionHandleStrategy.class);

    @Override
    public ResponseModel doHandle(Throwable throwable) {
        logger.error(throwable.getMessage(), throwable);
        BindingResult result = null;
        if (throwable instanceof BindException) {
            result = ((BindException) throwable).getBindingResult();
        }
        if (throwable instanceof MethodArgumentNotValidException) {
            result = ((MethodArgumentNotValidException) throwable).getBindingResult();
        }
        List<Map<String, Object>> list = Lists.newArrayList();
        if (result != null && result.hasErrors()) {
            List<ObjectError> errors = result.getAllErrors();
            for (ObjectError objectError : errors) {
                Map<String, Object> map = Maps.newHashMapWithExpectedSize(4);
                map.put("objectName", objectError.getObjectName());
                map.put("message", objectError.getDefaultMessage());
                if (objectError instanceof FieldError) {
                    map.put("type", "FieldError");
                    map.put("field", ((FieldError) objectError).getField());
                } else {
                    map.put("type", "ObjectError");
                }
                list.add(map);
            }
        }
        //list
        return ResponseModel.ERROR(HttpStatus.BAD_REQUEST.value(), "error.param.bad" + ": " + ToStringBuilder
                .reflectionToString(list, ToStringStyle.JSON_STYLE));

    }
}
